<?php
/**
* 名称：xheditor上传类。
* 描述：响应xheditor编辑器的上传文件响应，针对请求类型进行处理。
*/
final class XheditorUploader{
    /**
    * 描述：上传类别字面量值，针对xheditor的功能建立的。
    */
    const UPLOAD_TYPE_IMAGE='image';
    const UPLOAD_TYPE_DOCUMENT='document';
    const UPLOAD_TYPE_FLASH='flash';
    const UPLOAD_TYPE_VADIO='vadio';

    /**
    * 描述：每个上传类别允许的扩展名。
    */
    private $ExpandedName=array(
        self::UPLOAD_TYPE_IMAGE=>array('jpg','jpeg','gif','png'),
        self::UPLOAD_TYPE_DOCUMENT=>array('zip,rar,txt'),
        self::UPLOAD_TYPE_FLASH=>array('swf'),
        self::UPLOAD_TYPE_VADIO=>array('avi','mp4','flv','fv4')
    );

    /**
    * 描述：每个上传类别允许文件的大小。
    */
    private $Size=array(
        self::UPLOAD_TYPE_IMAGE=>1048576,    //1M
        self::UPLOAD_TYPE_DOCUMENT=>1048576, //1M
        self::UPLOAD_TYPE_FLASH=>5242880,    //5M
        self::UPLOAD_TYPE_VADIO=>10485760    //10M
    );

    /**
    * 描述：每个上传类别存放文件的子文件夹名称。
    */
    private $Folder=array(
        self::UPLOAD_TYPE_IMAGE=>'image',
        self::UPLOAD_TYPE_DOCUMENT=>'document',
        self::UPLOAD_TYPE_FLASH=>'flash',
        self::UPLOAD_TYPE_VADIO=>'vadio'
    );

    /**
    * 描述：错误信息存储量。
    */
    private $Error=NULL;

    /**
    * 描述：在"类别文件夹"下"动态创建的文件夹名称"，根据当前日期命名。
    */
    private $DynamicFolderName=NULL;

    /**
    * 描述：文件域名称。
    */
    public $FileControlName=NULL;

    /**
    * 描述：当前上传类别。
    */
    public $UploadType=NULL;

    /**
    * 描述：上传路径。
    */
    public $UpoadPath=NULL;

    /**
    * 描述：网址显示路径。
    */
    public $URIPath=NULL;

    /**
    * 描述：控制器入口函数。
    * @param  string require $type 请求控制器的操作符
    * @return void
    */
    public function __Construct($type=NULL,$path=NULL,$fileControlName=NULL){
        $this->UploadType=$type;
        $this->Path=$path;
        $this->FileControlName=$fileControlName;
    }

    /**
    * 描述：返回错误信息。
    * @return array
    */
    public function Error(){
        return $this->Error;
    }

    /**
    * 描述：文件上传函数。
    * @return void
    */
    public function Upload(){
        if(isset($this->UpoadPath)){
            if(!is_dir($this->UpoadPath)){
                $this->Error=array('err'=>'文件上传失败，上传目录不存在。','msg'=>'');
            }
        }
        else{
            $this->Error=array('err'=>'文件上传失败，请设置上传目录。','msg'=>'');
        }
        #根据控制器操作符，初始化上传参数。
        if(in_array($this->UploadType,array(self::UPLOAD_TYPE_IMAGE,self::UPLOAD_TYPE_DOCUMENT,self::UPLOAD_TYPE_FLASH,self::UPLOAD_TYPE_VADIO))){
            $this->DynamicFolderName=date('Ymj');
            $this->UploadTypeFolderName=$this->Folder[$this->UploadType];
        }
        else{
            $this->Error=array('err'=>'文件上传失败，上传类型错误。','msg'=>'');
            return;
        }
        #获取上传文件对象,filedata是xheditor上传表单文件域的统一名称。
        if(isset($_FILES[$this->FileControlName])){
            $fileObject=$_FILES[$this->FileControlName];
        }
        else{
            $this->Error=array('err'=>'文件上传失败，找不到文件域：'.$this->FileControlName.'。','msg'=>'');
            return;
        }
        #开始上传程式。
        if(UPLOAD_ERR_OK===$fileObject['error']){
            //文件大小不合适。
            if($fileObject['size']>$this->GetSizeByType()){
                $this->Error=array('err'=>'文件大小超过了限制，不能超过：'.$this->SizeFormat($this->GetSizeByType()).'。','msg'=>'');
                return;
            }
            //扩展名不合适。
            $fileExtension=$this->GetExtName($fileObject['name']);
            if(!in_array($fileExtension,$this->GetExpandedNameByType())){
                $this->Error=array('err'=>'文件格式不正确，只能是：'.join(',',$this->GetExpandedNameByType()).'。','msg'=>'');
                return;
            }
            //上传文件
            $filename=$filename=date('Ymd').time().rand(1000,2000);
            $uploadPath=$this->MakeUploadPath($this->UploadType);
            if(@move_uploaded_file($fileObject['tmp_name'],str_replace('//','/',$uploadPath).'/'.$filename)){
                $showPath=$this->MakeShowPath($filename);
                $this->Error=array('err'=>0,'msg'=>$showPath);
            }
            else{
                $this->Error=array('err'=>'文件移动失败。','msg'=>'');
            }
        }
        else{
            $this->Error=array('err'=>'文件上传失败，错误代码：'.$fileObject['error'].'。','msg'=>'');
        }
    }

    /**
    * 描述：生成上传路径。
    * @return string
    */
    private function MakeUploadPath(){
        Folder::Create($path=$this->UpoadPath.'/'.$this->UploadTypeFolderName.'/'.$this->DynamicFolderName);
        return $path;
    }

    /**
    * 描述：生成WWW显示路径，相对于网站架设根目录。
    * @param  string require $fileName 文件名
    * @return string
    */
    private function MakeShowPath($fileName){
        return $this->URIPath.'/'.$this->UploadTypeFolderName.'/'.$this->DynamicFolderName.'/'.$fileName;
    }

    /**
    * 描述：根据上传类别返回该类别允许上传的扩展名。
    * @return array
    */
    private function GetExpandedNameByType(){
        return $this->ExpandedName[$this->UploadType];
    }

    /**
    * 描述：根据上传类别返回该类别允许上传文件的大小。
    * @return number
    */
    private function GetSizeByType(){
        return $this->Size[$this->UploadType];
    }

    /**
    * 描述：从人理解的角度计算文件大小，并返回相应值。
    * @param  file   require $file 文件对象
    * @return string
    */
    private function SizeFormat($bytesize){
        $i=0;
        #当$bytesize 大于是1024字节时，开始循环，当循环到第4次时跳出；
        while(abs($bytesize)>=1024){
            $bytesize=$bytesize/1024;
            $i++;
            if($i==4){
                break;
            }
        }
        #将Bytes,KB,MB,GB,TB定义成一维数组；
        $units= array("bytes","kb","mb","gb","tb");
        $newsize=round($bytesize,2);
        return("$newsize $units[$i]");
    }

    /**
    * 描述：获取扩展名。
    * @param  file   require $file 文件对象
    * @return string
    */
    private function GetExtName($filename){
        $tempArray=explode('.', $filename);
        $value=strtolower($tempArray[count($tempArray)-1]);
        return $value;
    }
}